﻿/*
 * Created by SharpDevelop.
 * User: Intel
 * Date: 12.12.2014
 * Time: 14:33
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Threading;
using System.Collections.Generic;
namespace Region.Utils
{
  /// <summary>
  /// Description of TaskManager.
  /// </summary>
public class TaskManager: IDisposable
  {
    public delegate void TaskDelegate(Object Param,Task task);
  	public class Task
  	{
      public enum EStatus{None,Create,Work,End};
      public EStatus Status = EStatus.None;
      public Int32 TaskValue = 0;
      public Int32 TaskMax = 0;
      public String TaskTitle = "";
      public String TaskName = "Task";
      public Object taskParam;
      public TaskDelegate task;
      Int32 m_TaskID;
      public Int32 TaskID{get{return m_TaskID;}}
      public Task(TaskDelegate task,TaskManager TM){this.task = task;this.m_TaskID = TM.getNewTeskID();}
	  }
  	bool Work=false;
  	Object _lock = new Object();
  	Int32 TaskID=1;
  	Queue<Task> listTask = new Queue<TaskManager.Task>();
  	Dictionary<Int32,Task> m_RunTask = new Dictionary<Int32, TaskManager.Task>();
  	public Dictionary<Int32,Task> RunTask{get{lock(_lock){return new Dictionary<Int32,Task>(m_RunTask);}}}
  	protected Int32 getNewTeskID(){lock(_lock){return TaskID++;}}
  	public Task addTask(TaskDelegate task,String taskName = "Task", Object Param=null)
  	{
  		Task t = new Task(task,this);
  		t.taskParam = Param;
  		t.TaskName = taskName;
  		lock(_lock)
  		{
  			listTask.Enqueue(t);
  			t.Status = Task.EStatus.Create;
  		}
  		return t;
  	}
  	protected Task getTask()
  	{
  		lock(_lock)
  		{
  			if (listTask.Count==0) return null;
  			return listTask.Dequeue();
  		}
  	}
  	List<Thread> Workers = new List<Thread>();
  	public TaskManager(Int32 MaxThread = 1)
  	{
  	  Work = true;
  		for(Int32 i = 0;i<MaxThread;i++)
  		{
  			Thread w = new Thread(Worker);
  			w.Start();
  			Workers.Add(w);
  		}
  	}
  	public void Dispose()
    {
  	  Work = false;
  		for(Int32 i = 0; i<Workers.Count;i++)
  		  while(Workers[i].ThreadState != ThreadState.Stopped)
  		    Thread.Sleep(10);
    }
  	~TaskManager()
  	{
  	  Dispose();
  	}
  	void Worker()
  	{
  		while(Work)
  		{
  			Task t = getTask();
  			if (t!=null)
  			{
  				t.Status = Task.EStatus.Work;
  				lock(_lock){m_RunTask[t.TaskID]=t;}
  				t.task(t.taskParam,t);
  				t.Status = Task.EStatus.End;
  				lock(_lock){m_RunTask.Remove(t.TaskID);}
  			}
  			else
  				Thread.Sleep(10);
  		}
  	}
  }
}
